/* 
 * version: 1.01
 * 2015-12-22 Disiable g4jCallFinished()
 * 2015-12-23 g4jCall 增加自定义的 g4j_path
 * 2015-12-24 g4jCall 增加对FireFox的兼容，在函数中不再采用window.event(Firefox不支持)
 * 2015-12-25 g4jCall 增加初始化页面处理支持
 * 2015-12-28 g4jCall 解决ie8下兼容星问题：ie8不认event，所以必须用window.event!
 * 2016-04-12 g4jCall 增加对 _$_messageBox 的支持，这样可以自定义各类错误提示
 * 2016-05-18 g4jCall 增加对 无后缀.jspx 的支持
 * 2016-05-19 g4jCall 增加对 不指定event也能工作
 * 2016-06-02 g4jCall 增加对 Change 的事件响应的支持
 * 2016-06-19 增加 g4jSQL 对 sp 的直接调用
 * 2016-06-21 增加 g4jExport 数据导出
 * 2016-08-27 增加对AngularJS的支持－$scope!
 * 2016-08-27 增加对直接调用java方法的支持
 * 2017-03-10 g4jCall 增加对 g4j.alert 的支持，这样可以自定义各类错误提示
 * 2017-03-25 g4jCall 增加对 g4j.lasterror 的支持，全面优化取event的代码(g4jCall)，去掉了link和href和init等处理，改用标准化处理
 * 2017-04-02 g4jCall 增加对 mysql 的支持
 */
// $("#...").serialize() 可以用　serialize 生成url格式串！！！
if (typeof browser === 'undefined') {
    browser = {
        versions: function () {
            var u = navigator.userAgent, app = navigator.appVersion;
            return {//移动终端浏览器版本信息
                trident: u.indexOf('Trident') > -1, //IE内核
                presto: u.indexOf('Presto') > -1, //opera内核
                webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核
                gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') === -1, //火狐内核
                mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端
                ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端
                android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android终端或uc浏览器
                iPhone: u.indexOf('iPhone') > -1, //是否为iPhone或者QQHD浏览器
                iPad: u.indexOf('iPad') > -1, //是否iPad
                webApp: (u.indexOf('Safari') === -1), //是否web应该程序，没有头部与底部
                wxApp: (!!u.match(/AppleWebKit.*Mobile.*/) && u.toLowerCase().match(/MicroMessenger/i) !== null), //在微信中打开
                sinaWeiboApp: (!!u.match(/AppleWebKit.*Mobile.*/) && u.match(/WeiBo/i) === "weibo"), //在新浪微博客户端打开
                qqSpaceApp: (!!u.match(/AppleWebKit.*Mobile.*/) && u.match(/QQ/i) === "qq"), //在QQ空间打开
                wxIsReady: false
            };
        }(),
        language: (navigator.browserLanguage || navigator.language).toLowerCase(),
        point: {lng: 0.0, lat: 0.0},
        address: {
            describe: '得不到所在位置信息',
            streetNumber: '',
            street: '',
            district: '',
            city: '',
            province: '',
            surroundingPois: [],
            business: ''
        }
    };
}

if (browser.versions.mobile) {
    //判断是否是移动设备打开。browser代码在下面
    window.onload = window.onresize = function () {
        document.documentElement.style.fontSize = document.documentElement.clientWidth * 20 / 320 + 'px';
    };
} else {
    //否则就是PC浏览器打开
}

if (typeof g4j_js === 'undefined') {
    g4j_js = "OK";
    var _$_page = 1;
    var _$_pagecount = 1;
    var _$_query_button = null;
    var _$_messageBox = null;

    toString = function (s) {
        if (s === null) {
            return "null";
        }
        if (typeof s === 'undefined') {
            return "undefined";
        }
        if (typeof s === 'string') {
            return "'" + s + "'";
        }
        try {
            return JSON.stringify(s);
        } catch (e) {
            try {
                return e.toString();
            } catch (e) {
                return "object";
            }
        }
    };

    if (typeof String.prototype.startsWith !== 'function') {
        String.prototype.startsWith = function (prefix) {
            return this.slice(0, prefix.length) === prefix;
        };
    }

    if (typeof String.prototype.endsWith !== 'function') {
        String.prototype.endsWith = function (suffix) {
            return this.indexOf(suffix, this.length - suffix.length) !== -1;
        };
    }

    /**
     * 删除左右两端的空格
     */
    if (typeof String.prototype.trim !== 'function') {
        String.prototype.trim = function () {
            return this.replace(/(^\s*)|(\s*$)/g, '');
        };
    }

    /**
     * 删除左边的空格
     */
    if (typeof String.prototype.endsWith !== 'function') {
        String.prototype.ltrim = function () {
            return this.replace(/(^\s*)/g, '');
        };
    }

    /**
     * 删除右边的空格
     */
    if (typeof String.prototype.endsWith !== 'function') {
        String.prototype.rtrim = function () {
            return this.replace(/(\s*$)/g, '');
        };
    }

    /**
     * 删除所有的空格
     */
    if (typeof String.prototype.deleteBlanks !== 'function') {
        String.prototype.deleteBlanks = function () {
            return this.replace(/\s+/g, '');
        };
    }

    function isInvalidOrEmptyString(s) {
        if (typeof s === 'undefined' || s === null) {
            return true;
        }
        if (typeof s !== 'string') {
            s = s.toString();
        }
        s = s.trim();
        if (s.length <= 0) {
            return true;
        }
        return false;
    }

    function isInvalid(s) {
        return (typeof s === 'undefined' || s === null);
    }

    function isValid(s) {
        return !isInvalid(s);
    }

    function equalWithNoSpace(s, d) {
        if (s === null && d === null) {
            return true;
        }
        if (typeof s === 'undefined' && typeof d === 'undefined') {
            return true;
        }
        if (s === null || d === null || typeof s === 'undefined' || typeof d === 'undefined') {
            return false;
        }
        if (typeof s.deleteBlanks !== 'function' || typeof d.deleteBlanks !== 'function') {
            return false;
        }
        var s1 = s.deleteBlanks();
        var d1 = d.deleteBlanks();
        if (s1 === d1) {
            return true;
        }
        return false;
    }

// 第一种  
    function concatArray(mergeTo, mergeFrom) {
        if ($ && $.merge) {
            $.merge(mergeTo, mergeFrom);
            return mergeTo;
        }
        Array.prototype.push.apply(mergeTo, mergeFrom);
        return mergeTo;
    }

    var random = 1;
    function getRandom() {
        random++;
        return random;
    }

// 将json2追加到json1
    function extend(obj1, obj2) {
        for (var item in obj2) {
            obj1[item] = obj2[item];
        }
    }

    function getElementsByClass(className, parentElement) {
        var elems = document.all ? document.all : document.getElementsByTagName("*");
        var result = [];
        for (i = 0; i < elems.length; i++) {
            var j = elems[i];
            if ((" " + j.className + " ").indexOf(" " + className + " ") !== -1) {
                result.push(j);
            }
        }
        return result;
    }

    function disable_buttons_by_classname(button_class) {
        if (button_class === null || typeof button_class === "undefined") {
            button_class = "button";
        }
        var buttons = getElementsByClass(button_class);
        if (buttons === null) {
            return;
        }
        if (buttons.length <= 0) {
            return;
        }
        for (var i = 0; i < buttons.length; i++) {
            var this_button = buttons[i];
            this_button.disabled = true;
        }
    }

    function enable_buttons_by_classname(button_class) {
        if (button_class === null || typeof button_class === "undefined") {
            button_class = "button";
        }
        var buttons = getElementsByClass(button_class);
        if (buttons === null) {
            return;
        }
        if (buttons.length <= 0) {
            return;
        }
        for (var i = 0; i < buttons.length; i++) {
            var this_button = buttons[i];
            this_button.disabled = false;
        }
    }

    function deleteTableRowById(tr_id) {
        var tr = document.getElementById(tr_id);
        var table = tr.parentNode.parentNode;
        table.deleteRow(tr.rowIndex);
    }

    function deleteTableRow(tr) {
        var table = tr.parentNode.parentNode;
        table.deleteRow(tr.rowIndex);
    }

    function g4j_getPageName() {
        try {
            var name = location.href;
            var iPos = name.indexOf("://");
            if (iPos > 0) {
                name = name.substring(iPos + 3);
            }
            iPos = name.lastIndexOf("/");
            if (iPos > 0) {
                name = name.substring(iPos + 1);
            }
            iPos = name.indexOf(".");
            if (iPos > 0) {
                name = name.substring(0, iPos);
            }
            return name;
        } catch (e) {
            g4j.alert(e);
        }
    }

    function selectAll(check, table_id) {
        var objs = document.getElementsByTagName("INPUT");
        for (var i = 0; i < objs.length; i++) {
            if (objs[i].type.toUpperCase() !== "CHECKBOX") {
                continue;
            }
            if (objs[i].name.indexOf(table_id + "[") === 0 && objs[i].name.indexOf("]") === objs[i].name.length - 1) {
                objs[i].checked = check.checked;
            }
        }
    }

    var inputs_array = [];
    function g4j_disable() {
        var buttons = document.getElementsByTagName("INPUT");
        for (var i = 0; i < buttons.length; i++) {
            var oldstatus = buttons[i].disabled;
            var obj = buttons[i];
            inputs_array[i] = {"input": obj, "status": oldstatus};
            buttons[i].disabled = false;
        }
        show_loading();
    }

    function g4j_enable() {
        for (var i = 0; i < inputs_array.length; i++) {
            try {
                var obj = inputs_array[i].input;
                obj.disabled = inputs_array[i].status;
            } catch (e) {
                g4j.alert(e);
            }
        }
        /*try {
         g4j.alert("g4j_enable: " + element.name);
         if (element.disabled !== null) {
         element.disabled = false;
         }
         } catch (e) {
         g4j.alert(e);
         }*/
        hide_loading();
    }

    function alertMessage(msg, title, ok, afterJs) {
        if (msg === null || typeof msg === "undefined") {
            g4j.alert("Undefined msg in alertMessage().");
            return;
        }
        if (typeof dialog === "undefined") {
            g4j.alert(msg);
            console.log("WARNINGS: No js dialog defined, defined, please add js/plugin/dialog/dialog-min.js and js/plugin/dialog/ui-dialog.css in your HTML/JSP page:\n");
            return;
        }
        var okfunc = function () {
        };
        if (typeof afterJs === "function") {
            okfunc = afterJs;
        } else {
            if (typeof afterJs === "string") {
                okfunc = function () {
                    try {
                        eval(afterJs);
                    } catch (e) {
                        g4j.alert(e);
                    }
                };
            }
        }
        setTimeout(function () {
            var d = dialog({
                fixed: true,
                id: 'confirm',
                width: '480px',
                height: '50px',
                title: (typeof title === "undefined") ? '操作提示' : title,
                content: msg, //msg.replace(/\'/g, "“");
                okValue: (typeof ok === "undefined") ? '确认' : ok,
                ok: okfunc
            }).showModal();
        }, 0);
        return;
    }

    function selectValue(selectObj, value) {
        var options = selectObj.options; //[oCars.selectedIndex].text 
        for (var i = 0; i < options.length; i++) {
            if (options[i].value === value) {
                options[i].selected = true;
            }
        }
    }

    function initValueList(name, value, value_list) {
        try {
            if (name === null) {
                g4j.alert("initValueList says: name is null");
                return;
            }
            var ddlb = document.getElementById(name);
            if (ddlb === null) {
//g4j.alert("initValueList says: no element with the name of '" + name + "'");
                return;
            }
            switch (ddlb.tagName) {
                case "INPUT":
                    ddlb.value = value;
                    break;
                case "SELECT":
                    try {
                        //g4j.alert(ddlb.tagName + ": id=" + name + "/value=" + value + "/value_list.length=" + value_list.length);
                        if (value_list.length > 0) {
                            ddlb.length = 0;
                            ddlb.add(new Option('-请选择-', ''));
                            for (var i = 0; i < value_list.length; i++) {
                                var rec = value_list[i];
                                var option = new Option(rec.DISPLAY, rec.VALUE);
                                if (rec.VALUE === value) {
                                    option.selected = true;
                                }
                                ddlb.add(option);
                            }
                        }
                    } catch (e) {
                        selectValue(ddlb, value);
                        return;
                    }
                    break;
                default:
                    ddlb.innerText = value;
            }
        } catch (e) {
            g4j.alert(e);
        }
        return;
    }

    function set_select_value(data) {
        var name = data.name;
        var value = data.value;
        var value_list = data.valueList || data.value_list;
        if (typeof name === 'undefined' || name === null) {
            g4j.alert("set_select_value says: name is null or undefined");
            return;
        }
        if (typeof value === 'undefine') {
            value = "";
        }
        if (typeof value_list === 'undefined') {
            g4j.alert("set_select_value says: " + name + "'s value_list/valueList undefined");
            return;
        }
        var ddlb = document.getElementById(name);
        if (ddlb === null) {
            var objs = document.getElementsByName(name);
            if (objs.length <= 0) {
                g4j.alert("set_select_value says: no element with the name of '" + name + "'");
                return;
            }
            ddlb = objs[0];
        }
        if (ddlb.tagName !== "SELECT") {
            g4j.alert("set_select_value says: no SELECT element with the name of '" + name + "'");
            return;
        }
        var oldlen = ddlb.length;
        ddlb.length = 0;
        ddlb.add(new Option('-请选择-', ''));
        var changeflag = false;
        if (value_list !== null && value_list.length > 0) {
            //g4j.alert("json:\n" + JSON.stringify(value_list));
            for (var i = 0; i < value_list.length; i++) {
                var rec = value_list[i];
                var option = null;
                if (typeof rec.DISPLAY !== 'undefined' || typeof rec.VALUE !== 'undefined') {
                    option = new Option(rec.DISPLAY, rec.VALUE);
                } else
                if (typeof rec.NAME !== 'undefined' || typeof rec.ID !== 'undefined') {
                    option = new Option(rec.NAME, rec.ID);
                }
                if (option === null) {
                    g4j.alert("Return data format error: require DISPLAY and VALUE or NAME and ID for the SELECT Element!");
                    break;
                }
                ddlb.add(option);
            }
        }
        for (var i = 0; i < ddlb.options.length; i++) {
            var option = ddlb.options[i];
            if (typeof value === 'function') {
                if (value(ddlb, i, data.value)) {
                    return true;
                }
            } else {
                var display = option.innerHTML.trim();
                if (display === value || data.value === option.value) {
                    if (!ddlb.options[i].selected) {
                        ddlb.options[i].selected = true;
                        $(ddlb).change();
                        return true;
                    }
                    break;
                }
            }
        }
        // 当列表为空时，也要提示change事件
        if (oldlen !== ddlb.length) {
            $(ddlb).change();
        }
        return true;
    }

    function set_element_value(data) {
        var name = data.name;
        var value = data.value;
        if (name === null || typeof name === 'undefined') {
            g4j.alert("set_element_value says: name is null or undefined");
            return;
        }
        var ele = document.getElementById(name);
        if (ele === null) {
            var objs = document.getElementsByName(name);
            if (objs.length <= 0) {
                g4j.alert("set_element_value says: no element with the name of '" + name + "'");
                return;
            }
            ele = objs[0];
        }
        try {
            ele.innerHTML = value;
        } catch (e) {
            g4j.alert(ele);
        }
    }

    function set_table_value(data) {
        _$_page = data.page;
        _$_pagecount = data.pageCount;
        var name = data.name;
        var value_list = data.resultset;
        var count = data.count;
        var rowsPerPage = data.rowsPerPage;
        if (name === null) {
            g4j.alert("set_table_value says: name is null");
            return;
        }
        var pageList = [];
        for (var i = 0; i < _$_pagecount; i++) {
            var pageNo = i + 1;
            pageList[i] = {"VALUE": pageNo, "DISPLAY": pageNo};
        }
        set_element_value({"name": "g4j_" + name + "Page", "value": _$_page});
        set_element_value({"name": "g4j_" + name + "PageCount", "value": _$_pagecount});
        set_element_value({"name": "g4j_" + name + "Count", "value": count});
        set_element_value({"name": "g4j_" + name + "RowsPerPage", "value": rowsPerPage});
        try {
            set_select_value({"name": "g4j_" + name + "PageList", "value": _$_page, "valueList": pageList});
        } catch (e) {
            g4j.alert(e);
        }
        var objTable = document.getElementById(name);
        if (objTable === null) {
            g4j.alert("set_table_value says: no element with the name of '" + name + "'");
            return;
        }
        for (var i = objTable.rows.length - 1; i >= 1; i--) {
            objTable.deleteRow(i);
        }
        for (var i = 0; i < value_list.length; i++) {
            var rec = value_list[i];
            var objNewRow = objTable.insertRow(objTable.rows.length);
            objNewRow.className = 'g4j_tr';
            if ((i % 2) === 1) {
                objNewRow.className = "g4j_tr odd";
            }
            $(objNewRow).mouseover(function () {
                $(this).addClass("highlight");
            });
            $(objNewRow).mouseout(function () {
                $(this).removeClass("highlight");
            });
            objNewRow.id = objTable.rows.length - 1;
            try {
                for (var col = 0; col < objTable.rows[0].cells.length; col++) {
                    var objNewCell = objNewRow.insertCell(col);
                    objNewCell.setAttribute("col", col);
                    objNewCell.setAttribute("row", i);
                    var colname = objTable.rows[0].cells[col].innerText;
                    colname = colname.replace(/\r\n\t\u0020/g, "");
                    if (colname === "") {
                        //objNewCell.innerHTML = objTable.rows[0].cells[col].innerHTML;
                        var pk = new String(rec["PK"]);
                        objNewCell.innerHTML = "<input type=\"checkbox\" name=\"" + name + "[" + (i + 1) + "]\" value=\"" + pk + "\" >";
                        objNewCell.setAttribute("align", "center");
                    } else {
                        var s2 = new String(rec[colname]);
                        objNewCell.innerHTML = "&nbsp;" + s2 + "&nbsp;";
                    }
                }
            } catch (e) {
                g4j.alert(e);
            }
        }
    }

    function set_input_value(data) {
        if (data === null || typeof data !== 'object') {
            g4j.alert("set_input_value says: data is null or not a JSON object");
            return;
        }
        var name = data.name;
        if (typeof name === 'string' && name.trim().length > 0) {
            name = name.trim();
            var objs = document.getElementsByName(name);
            for (var i = 0; i < objs.length; i++) {
                if ((objs[i].tagName === "INPUT" || objs[i].tagName === "TEXTAREA" || objs[i].tagName === "SELECT") && objs[i].value !== data.value) {
                    objs[i].value = data.value;
                    if (typeof objs[i].change === 'function') {
                        objs[i].change();
                    }
                }
            }
        }
        return;
    }

    function set_element_html(data) {
        var name = data.name;
        var value = data.value;
        if (name === null || typeof name === 'undefined') {
            g4j.alert("set_element_html says: name is null or undefined");
            return;
        }
        if (value === null || typeof value === 'undefined') {
            g4j.alert("set_element_html says: " + name + "'s value is null or undefined");
            return;
        }
        var input = document.getElementById(name);
        if (input === null) {
            var objs = document.getElementsByName(name);
            if (objs.length <= 0) {
                g4j.alert("set_element_html says: no element with the name of '" + name + "'");
                return;
            }
            input = objs[0];
        }
        input.innerHTML = value;
        return;
    }

    function initPage(name, html) {
        try {
            if (name === null || html === null) {
                g4j.alert("initPage says: name is null or html == null");
            }
            if (name.toLowerCase() === "body") {
                document.body.innerHTML = html;
            } else {
                g4j.alert("initPage Not supported for " + name + ", but BODY");
            }
        } catch (e) {
            g4j.alert(e);
        }
    }

    function jsonHas(o, key) {
        return (o[key] !== undefined);
    }

    function jsonSet(o, key, value, replace) {
        if (typeof replace === 'undefined' || replace === null || replace === "" || replace === 0) {
            replace = false;
        }
        if (typeof key !== 'string' || typeof value === 'undefined') {
            return;
        }
        if (key === '') {
            return;
        }
        if (o[key] !== undefined) {
            if (o[key] !== value && !replace) {
                console.log("WARNING: Find more than one input for name '" + key + "'. their values is NOT equal:(\"" + o[key] + "\" != \"" + value + "\")");
            }
            delete o[key];
        }
        o[key] = value || '';
    }

    function getFormInputs(form) {
        var o = {};
        var a = $(form).serializeArray();
        $.each(a, function () {
            jsonSet(o, this.name, encodeURI(this.value), false);
        });
        $(form).find(":file").each(function (e) {
            var name = $(this).attr('name');
            if (typeof name !== 'string' || name === '') {
                g4j.alert("WARNING: INPUT[TYPE=FILE] must has the attribute of 'NAME'.");
                name = "ANOYMOUS";
            }
            jsonSet(o, "g4j_hasfile", true, true);
            var path = $(this).attr('path') || $(this).attr('data-path');
            if (typeof path === 'string' && path.trim().length > 0) {
                jsonSet(o, name + "[path]", path, true);
            }
        });
        return o;
    }

    function getPageInputs() {
        var o = {};
        var objs = document.getElementsByTagName("INPUT");
        var checks = "";
        for (var i = 0; i < objs.length; i++) {
            if (objs[i].type.toUpperCase() === "BUTTON" || objs[i].type.toUpperCase() === "SUBMIT" || objs[i].type.toUpperCase() === "RESET") {
                continue;
            }
            if (objs[i].type.toUpperCase() === "CHECKBOX" || objs[i].type.toUpperCase() === "RADIO") {
                if (!objs[i].checked) {
                    continue;
                }
                if (objs[i].name !== null && objs[i].name === "list_checkbox") {
                    if (checks.length > 0) {
                        checks += ",";
                    }
                    checks += "\"" + encodeURI(objs[i].value) + "\"";
                    continue;
                }
            }
            jsonSet(o, objs[i].name, encodeURI(objs[i].value), false);
        }
        if (checks.length > 0) {
            jsonSet(o, "list_checkbox", JSON.parse("[" + objs[i].value + "]"), false);
        }
        var objs = document.getElementsByTagName("SELECT");
        for (var i = 0; i < objs.length; i++) {
            jsonSet(o, objs[i].name, encodeURI(objs[i].value), false);
        }
        var objs = document.getElementsByTagName("TEXTAREA");
        for (var i = 0; i < objs.length; i++) {
            jsonSet(o, objs[i].name, encodeURI(objs[i].value), false);
        }
        return o;
    }

    // 调用方法：getActionInputs(event);
    /*function getActionInputs(evt) {
     这个有兼容性问题，早期g4jCall等用的是取整个页面的输入的方法
     var input_obj = null;
     if (typeof evt !== 'undefined') {
     input_obj = (evt.srcElement || evt.target);
     }
     if (typeof input_obj === 'undefined' || input_obj === null || typeof input_obj.form === 'undefined') {
     return getPageInputs();
     }
     return getFormInputs(input_obj.form);
     }*/

    // 调用方法：getActionInputs(event);
    function getActionInputs(evt) {
        var input_obj = null;
        if (isEventObject(evt)) {
            input_obj = (evt.srcElement || evt.target);
        }
        var jsonInputs = getPageInputs();
        if (typeof input_obj !== 'undefined' && input_obj !== null && typeof input_obj.form !== 'undefined') {
            var jsonForms = getFormInputs(input_obj.form);
            for (var p in jsonForms) {
                // 以和input在同一form中的数据替换原来整页中的键值对
                jsonSet(jsonInputs, p, jsonForms[p], true);
            }
        }
        return jsonInputs;
    }

    function g4jActionProc(input_name, actions) {
        var recall = false;
        var input = null;
        if (input_name !== "Page" && input_name !== '(null)') {
            var inputs = document.getElementsByName(input_name);
            if (inputs !== null && inputs.length > 0) {
                /*if (inputs.length !== 1) {
                 console.log("WARNINGS: There are " + inputs.length + " HTMLElement input named by '" + input_name + "'.");
                 }*/
                input = inputs[0];
            }
        }
        for (var iAction = 0; iAction < actions.length; iAction++) {
            var actionThis = actions[iAction];
            var nextStep = actionThis.actionType;
            switch (nextStep) {
                case 'recall':
                    recall = true;
                    continue;
                case 'set_select_value':
                    set_select_value(actionThis);
                    continue;
                case "set_table_value":
                    if (input !== null) {
                        _$_query_button = input;
                    } else {
                        g4j.alert("Cannot not find the HTMLElement of input named by '" + input_name + "', therefore page-function was disabled! .");
                        return;
                    }
                    set_table_value(actionThis);
                    continue;
                case "set_url_value":
                    location.href = actionThis.value;
                    continue;
                case "set_javascript_value":
                    //g4j.alert(actionThis.value);
                    try {
                        eval(actionThis.value);
                    } catch (e) {
                        g4j.alert("Operate successfully. But cannot to execute " + actionThis.value + "\nDetailed error:" + e + "\nYou may reload page to show the result");
                    }
                    continue;
                case 'set_input_value':
                    set_input_value(actionThis);
                    continue;
                case "alert":
                    g4j.alert(actionThis.errmsg);
                    continue;
                case "init_js_value":
                    try {
                        var js = actionThis.name + "=" + actionThis.value + ";";
                        eval(js);
                    } catch (e) {
                        g4j.alert(e);
                    }
                    continue;
                case "set_html_value":
                    set_element_html(actionThis);
                    continue;
                case 'init_page':
                    initPage(actionThis.name, actionThis.value);
                    continue;
                default:
                    g4j.alert("Error: The server returns unknown actionType - " + actionThis.actionType);
                    g4j_enable();
                    return recall;
            }
            g4j_enable();
            return recall;
        }
    }

    function jsonAppendFrom(somejson, otherjson) {
        if (somejson === null) {
            somejson = {};
        }
        if (typeof somejson !== 'object') {
            g4j.alert("g4j.js>addProperties() said: TRY to add properties to non-object!");
            return;
        }
        if (typeof otherjson !== "object") {
            g4j.alert("g4j.js>addProperties() said: TRY to add properties from non-object!");
            return;
        }
        var p;
        for (p in otherjson) {
            var keyName = new String(p);
            if (p.indexOf("$") === 0) {
                // $开始的元素不增加
                continue;
            }
            if (typeof otherjson[p] === 'function') {
                // $函数不增加
                continue;
            }
            if (typeof otherjson[p] === 'object') {
                // 注：这里不要递归！否则会死循环！！！
                //somejson = jsonAppendFrom(somejson, otherjson[p]);
                continue;
            }
            somejson[keyName] = otherjson[p];
        }
        return somejson;
    }

    function g4jTranslateJsonResult(res) {
        if (parseInt(res.errcode) !== 0) {
            return res;
        }
        if (typeof res.COL1 !== 'undefined' && typeof res.COL2 !== 'undefined') {
            res.errcode = res.COL1;
            res.errmsg = res.COL2;
            delete res.COL1;
            delete res.COL2;
            if (parseInt(res.errcode) !== 0) {
                return res;
            }
        }
        if (typeof res.errmsg === 'string' && res.errmsg.indexOf("{") === 0 && res.errmsg.lastIndexOf("}") === res.errmsg.length - 1) {
            try {
                //s = JSON.parse(res.errmsg);
                var errmsgjson = {};
                eval("errmsgjson=" + res.errmsg);
                delete res.errmsg;
                for (var p in errmsgjson) {
                    res[p] = errmsgjson[p];
                }
            } catch (e) {
                var s = res.errmsg;
                res.errmsg = "Error: " + e + "\nError JSON text:" + s + "\n";
            }
        }
        return res;
    }
    var statusDialog = null;

    function parseResult(res) {
        if (res === null) {
            g4j.alert("parseResult said: res is null.");
            return null;
        }
        if (typeof res === 'undefined') {
            g4j.alert("parseResult said: res is undefined");
            return null;
        }
        if (typeof res === 'string') {
            try {
                var str = res;
                eval("res = " + str + "");
                if (typeof res !== 'object') {
                    g4j.alert("Cannot get a JSON from \"" + str + "\".");
                    return null;
                }
            } catch (e) {
                g4j.alert("parseResult said: res NOT a JSON string - \"" + str + "\".");
                return null;
            }
        } else {
            // 不是string，才判断它是不是object，因为json是object
            if (typeof res !== 'object') {
                g4j.alert("parseResult said: res NOT a JSON object");
                return null;
            }
        }
        if (typeof res.errcode === 'undefined') {
            g4j.alert("parseResult said: No 'errcode' in the JSON of the arguement named 'res'." + JSON.stringify(res));
            return null;
        }
        if (parseInt(res.errcode) !== 0) {
            if (typeof res.errmsg === 'undefined') {
                g4j.alert("parseResult said: No 'errmsg' in the JSON named 'res' when its errcode != 0." + JSON.stringify(res));
                return null;
            }
            g4j.alert(res.errmsg, "提示");
            return null;
        }
        return res;
    }

    function _g4j_beforeCall(arg, action, param) {
        if (typeof param !== 'object' || param === null) {
            return true;
        }
        var beforeCall = arg.before;
        if (typeof beforeCall === 'string' && beforeCall.trim().length > 0) {
            var oldscript = beforeCall;
            beforeCall = function (action, param) {
                // 因为以前有用以下变量名作为res的名
                try {
                    return eval(oldscript);
                } catch (exp) {
                    g4j.alert(exp);
                    return false;
                }
            };
        }
        if (typeof beforeCall === 'function') {
            return beforeCall(action, param);
        }
        return true;
    }

    function _g4j_afterCall(arg, res) {
//        if (statusDialog !== null) {
//            statusDialog.remove();
//            statusDialog = null;
//        }
        if (typeof arg.input_obj === 'undefined') {
            arg.input_obj = null;
        }
        if (typeof res.input === 'undefined' || res.input === '') {
            res.input = arg.input;
        }
        if (typeof res.inputParam === 'undefined' && $.isPlainObject(arg.param)) {
            res.inputParam = arg.param;
        }
        var thenFunc = arg.after || arg.then;
        var jsonResult = parseResult(res);
        if (jsonResult === null) {
            if (typeof thenFunc === 'string' && thenFunc.trim().length > 0) {
                var oldscript = thenFunc;
                thenFunc = function (res) {
                    // 因为以前有用以下变量名作为res的名
                    var jsonResult = res;
                    var resultJson = res;
                    var json = res;
                    var e = res;
                    try {
                        return eval(oldscript);
                    } catch (exp) {
                        g4j.alert(exp);
                        return false;
                    }
                };
            }
            if (typeof thenFunc === 'function') {
                return thenFunc(res);
            }
            return false;
        }
        if (typeof jsonResult.errmsg === 'undefined' && typeof jsonResult.alert !== 'undefined') {
            jsonResult.errmsg = jsonResult.alert;
            delete jsonResult.alert;
        }
        if (typeof jsonResult.errmsg === 'undefined' && typeof jsonResult.alert !== 'msg') {
            jsonResult.errmsg = jsonResult.msg;
            delete jsonResult.msg;
        }
        if (typeof jsonResult.errmsg === 'undefined' && typeof jsonResult.alert !== 'error') {
            jsonResult.errmsg = jsonResult.error;
            delete jsonResult.error;
        }
        // 这是一个json信息
        for (var p in jsonResult) {
            var name = p;
            var value = jsonResult[p];
            if (name === 'redirect') {
                location.href = value;
                continue;
            }
            if (name === 'reload') {
                location.reload();
                continue;
            }
            if (name === 'alert' || name === 'msg' || name === 'error' || name === 'errmsg') {
                if (typeof value !== 'undefined' && value !== '' && value !== 'OK') {
                    g4j.alert(value);
                }
                continue;
            }
            if (name === 'js' || name === 'script' || name === 'jscript') {
                try {
                    eval(value);
                } catch (e) {
                    g4j.alert(e);
                }
                continue;
            }
            if (name.indexOf('input.') === 0) {
                var input_name = name.substring('input.'.length);
                set_input_value({name: input_name, value: value});
                continue;
            }
            if (name.indexOf('select.') === 0) {
                var input_name = name.substring('select.'.length);
                set_select_value({name: input_name, value: value, valueList: []});
                continue;
            }
            if (name === 'actions') {
                var input = jsonResult.g4j_control || jsonResult.input;
                if (typeof input === 'undefined') {
                    input = "(null)";
                } else {
                    input = decodeURI(input);
                }
                if (g4jActionProc(input, value)) {
                    g4j.alert("g4j.js said: recall is required.");
                    g4jCall(jsonResult.param.arg1, jsonResult.param.arg2, jsonResult.param.arg3);
                }
                continue;
            }
        }
        if (typeof thenFunc === 'function') {
            return thenFunc(jsonResult);
        }
        if (typeof thenFunc === 'string' && thenFunc.trim().length > 0) {
            try {
                thenFunc = thenFunc.replace(/jsonResult/g, 'res');//兼容
                thenFunc = thenFunc.replace(/resultJson/g, 'res');//兼容
                thenFunc = thenFunc.replace(/json/g, 'res');//兼容
                return eval(thenFunc);
            } catch (e) {
                g4j.alert(e);
            }
        }
        return true;
    }


    function g4j_jscall(str, defaultFunc, arg1, arg2, arg3, arg4, arg5) {
        var f = null;
        if (typeof str === 'function') {
            f = str;
            return f(arg1, arg2, arg3, arg4, arg5);
        }
        if (typeof str === 'string') {
            str = str.replace(/\s/g, '');
            //str = str.trim();
            if (str.length > 0) {
                str = str.replace(/\(jsonResult\)/g, '(res)');//兼容
                str = str.replace(/\(resultJson\)/g, '(res)');//兼容
                str = str.replace(/\(json\)/g, '(res)');//兼容
                str = str.replace(/\(action,param\)/g, '(res)');//兼容
                if (str.indexOf('(res)') > 0) {
                    str = str.replace(/\(res\)/g, '(arg1, arg2, arg3, arg4, arg5)');
                    str = str.replace(/\(res\,/g, '(arg1, arg2, arg3, arg4, arg5,');
                    str = str.replace(/\,res\)/g, ',arg1, arg2, arg3, arg4, arg5)');
                    str = str.replace(/\,res\,/g, ',arg1, arg2, arg3, arg4, arg5,');
                }
                try {
                    var eval_res = eval(str);
                    if (typeof eval_res === 'function') {
                        f = eval_res;
                        return f(arg1, arg2, arg3, arg4, arg5);
                    }
                    return eval_res;
                } catch (e) {
                    g4j.alert(e);
                }
            }
        }
        f = defaultFunc;
        return f(arg1, arg2, arg3, arg4, arg5);
    }

    function g4jUrlAction() {
        var str = location.pathname;
        if (str.substring(str.length - 1, str.length) === '/') {
            str += "index.jsp";
        }
        var iDotPos = str.lastIndexOf(".");
        if (iDotPos > 0) {
            str = str.substring(0, iDotPos);
        }
        return str;
    }

    function isEventObject(maybeevt) {
        if (maybeevt !== null && typeof maybeevt === 'object') {
            if (typeof (maybeevt.srcElement || maybeevt.target) !== 'undefined' && typeof maybeevt.type !== 'undefined') {
                return true;
            }
        }
        return false;
    }

    function g4jGetAttr(element, attrname) {
        if (typeof element === 'undefined') {
            return null;
        }
        if (element === null) {
            return null;
        }
        if (element === document) {
            element = document.body;
        }
        if (typeof element.getAttribute !== 'function') {
            g4j.alert("ASSERT Failure: element.getAttribute is not a FUNCTION!!!!");
            return null;
        }
        return element.getAttribute(attrname);
    }

    // 将 name 由 abc-efg 变成 thisAbcEfg 就是首字母大写，-字符或_字符也将后一个字母大写 
    function g4jCapUpper(s) {
        var returnString = "";
        var toUpper = true;
        for (var i = 0; i < s.length; i++) {
            var c = s.substring(i, i + 1).toLowerCase();
            if (c === '-' || c === '_') {
                toUpper = true;
                continue;
            }
            if (toUpper) {
                c = c.toUpperCase();
                toUpper = false;
            }
            returnString += c;
        }
        return returnString;
    }

    function g4jReadFromEvent(evt) {
        var info = {async: true, modulespecified: false};
        info.input_obj = (evt.srcElement || evt.target);
        info.data_link = g4jGetAttr(info.input_obj, 'data-link') || g4jGetAttr(info.input_obj, 'link');
        info.data_module = g4jGetAttr(info.input_obj, 'data-module');// || g4jUrlAction();
        info.input_alias = g4jGetAttr(info.input_obj, 'data-alias') || g4jGetAttr(info.input_obj, 'alias');// || g4jUrlAction();
        info.data_method = g4jGetAttr(info.input_obj, 'data-method') || g4jGetAttr(info.input_obj, 'method');
        info.data_async = g4jGetAttr(info.input_obj, 'data-async') || g4jGetAttr(info.input_obj, 'async');
        if (typeof info.data_async !== 'undefined') {
            if (info.data_async === 'false' || info.data_async === false) {
                info.async = false;
            }
        }
        info.input_name = info.input_obj.name; //evt.srcElement(IE)/evt.target(Firefox)
        if (typeof info.input_name === 'undefined'){
            // 对于象SPAN之类，可能没有标准name属性，所以必须用 getAttribute 获取name
            info.input_name = info.input_obj.getAttribute("name");
        }
        info.event_name = evt.type;
        if (typeof info.input_name === 'undefined') {
            if (info.input_obj === document) {
                info.input_name = "Page";
                info.input_obj = document.body;
                info.data_module = g4jGetAttr(info.input_obj, 'data-module') || g4jGetAttr(info.input_obj, 'data-bind');
                ;
            } else {
                info.input_name = "";
            }
        }
        info.action_name = info.data_module;
        if (typeof info.action_name === 'string' && info.action_name.length > 0) {
            if (!info.action_name.endsWith(".jspx")) {
                info.action_name += ".jspx";
            }
            info.modulespecified = true;
        }
        if (info.event_name === 'load') {
            info.event_name = "Init";
        }
        info.input = g4jGetAttr(info.input_obj, 'data-input');
        info.before = g4jGetAttr(info.input_obj, 'data-before') || g4jGetAttr(info.input_obj, 'onsubmit') || g4jGetAttr(info.input_obj, 'onselect');
        info.after = g4jGetAttr(info.input_obj, 'data-after') || g4jGetAttr(info.input_obj, 'onended');
        info.param = g4jGetAttr(info.input_obj, 'data-param') || "{}";
        if (!isValid(info.param)) {
            g4j.alert("Assert failed: param is invalid - here(key 2080)!!!!");
            return null;
        }
        try {
            var reg = /\b(this)\b/g;
            info.param = info.param.replace(reg, "info.input_obj");
            info.param = eval("(" + info.param + ")");
        } catch (e) {
            g4j.alert("Cannot parse these script: " + info.param);
            return null;
        }
        if (!$.isPlainObject(info.param)) {
            g4j.alert("Invalid data-param value! its ID is " + g4jGetAttr(info.input_obj, 'id') + " its NAME is " + g4jGetAttr(info.input_obj, 'name'));
            return null;
        }
        if (typeof info.before !== 'undefined') {
            jsonSet(info.param, "before", info.before);
        }
        if (typeof info.after !== 'undefined') {
            jsonSet(info.param, "after", info.after);
        }
        if (typeof info.input_obj.value !== 'undefined') {
            jsonSet(info.param, "thisValue", info.input_obj.value);
        }
        if (typeof info.data_link !== 'undefined') {
            jsonSet(info.param, "thisLink", info.data_link);
        }
        for (var p in info.input_obj) {
            if (typeof info.input_obj.getAttribute === 'undefined') {
                break;
            }
            var val = info.input_obj.getAttribute(p);
            if (val !== null && typeof p === 'string' && p.length > 0) {
                if (p.substring(0, 2).toLowerCase() === 'on'
                        || p.substring(0, 10).toLowerCase() === 'data-after'
                        || p.substring(0, 11).toLowerCase() === 'data-before'
                        || p.substring(0, 9).toLowerCase() === 'data-then'
                        || p.substring(0, 11).toLowerCase() === 'data-module'
                        || p.substring(0, 11).toLowerCase() === 'data-bind'
                        || p.substring(0, 11).toLowerCase() === 'data-method') {
                    // 跳过 onchange onclick onload data-param 等
                    continue;
                }
                var attrName = "this" + g4jCapUpper(p);
                //info.param[attrName] = val;
                jsonSet(info.param, attrName, val);
            }
        }
        return info;
    }

    /*
     * g4jCall()
     * @event {type} event
     * @returns {undefined|Boolean}
     * @example: g4jCall(event,{ 'id':1, 'name':'zhangwengao'}, location.pathname)
     * @example: g4jCall(event,{ 'id':1, 'name':'zhangwengao'})
     * @example: g4jCall(event)
     * @example: g4jCall()
     */
    function g4jCall(arg1, arg2, arg3) {
        var async = true;
        //var before_func = null;
        //var after_func = null;
        //var then_func = null;
        //var action_name = null;
        //var input_name = null; //evt.srcElement(IE)/evt.target(Firefox)
        //var event_name = null;
        //var input_obj = null;
        var evt = null;
        var control = {
            param: {}
        };
        if (isEventObject(arg1)) {
            // 最早设计时第一个参数是 event，第二个是 param 第三个是 jspx
            evt = arg1;
        } else {
            if (typeof arg1 === 'object' && isEventObject(arg1.event)) {
                // 第一个 param 也有可能传 event 对象
                evt = arg1.event;
                delete arg1['event'];
            } else {
                if (typeof arg2 === 'object' && isEventObject(arg2.event)) {
                    // 第二个 param 也有可能传 event 对象
                    evt = arg2.event;
                    delete arg2['event'];
                } /*else {
                    var maybeevt = null;
                    try {
                        maybeevt = arguments.callee.caller.arguments[0]||window.event;
                    } catch(e){}
                    if (isEventObject(maybeevt)) {
                        evt = maybeevt;
                    }
                }*/
            }
        }
        if (null !== evt) {
            control = g4jReadFromEvent(evt);
            async = control.async;
        }
        var args = [];
        // 第一个参数有几种可能：event, string("Init" "href"或"link"), json({....}) 
        if (typeof arg1 !== 'undefined' && arg1 !== evt) {
            args[args.length] = arg1;
        }
        if (typeof arg2 !== 'undefined' && arg2 !== evt) {
            args[args.length] = arg2;
        }
        // 这里为了兼容以前的写法！
        if (typeof arg3 !== 'undefined' && arg3 !== evt) {
            if (typeof arg3 === "string") {
                control.action_name = arg3;
                if (!control.action_name.endsWith(".jspx") && control.action_name.length > 0) {
                    control.action_name += ".jspx";
                    control.modulespecified = true;
                }
            } else {
                args[args.length] = arg1;
            }
        }
        // 为兼容以前版本的写法
        // g4jCall()
        // g4jCall(event)
        // g4jCall(event,{});
        // g4jCall(event, {}, 'a.jspx')
        // g4jCall(event, {}, 'a')
        for (var i = 0; i <= 1; i++) {
            if (typeof args[i] === "undefined" || args[i] === null) {
                continue;
            }
            if (typeof args[i] === "string") {
                if (args[i].toLowerCase() === "init") {
                    g4j.alert("Depricted - g4jCall('init').\nPlease use BODY's onload trigger to realize the function\ne.g. <body onload=\"g4jCall()\">...</body>");
                    return false;
                }
                if (args[i].toLowerCase() === "href" || args[i] === "link") {
                    g4j.alert("Depricted: please add 'event' to your JSON parameter to specify the event_name\n e.g. g4jCall(\"link\", {\"somekey\": somevalue, \"input\": \"ActionButton\"});\n should reform to \n g4jCall({\"somekey\": somevalue, \"input\": \"ActionButton\", \"event\": \"click\"});");
                    return false;
                }
                g4j.alert("Invalid No. 1 Argument for g4jCall: '" + arg1 + "', please check!");
                return;
            } else if (typeof args[i] === "object") {
                // args[i] 是一个json
                if (typeof args[i].event === 'object') {
                    // 前面应该已经处理并去掉event之类的成员了，所以这里报错！
                    g4j.alert("Assert failed: please contact the developer - Grant!");
                }
                if (typeof args[i].input === "string" && args[i].input.length > 0) {
                    control.input_name = args[i].input;
                    delete args[i]['input'];
                    if (control.input_name.toLowerCase() === 'page') {
                        control.input_obj = document;
                    }
                }
                if (typeof args[i].event === "string" && args[i].event.length > 0) {
                    control.event_name = args[i].event;
                    delete args[i]['event'];
                }
                if (typeof args[i].jspx === "string") {
                    control.action_name = args[i].jspx;
                    if (!control.action_name.endsWith(".jspx") && control.action_name.length > 0) {
                        control.action_name += ".jspx";
                    }
                    delete args[i]['jspx'];
                    control.modulespecified = true;
                }
                if (typeof args[i].before === "function" || typeof args[i].before === "string") {
                    control.before = args[i].before;
                    delete args[i]['before'];
                }
                if (typeof args[i].after === "function" || typeof args[i].after === "string") {
                    control.after = args[i].after;
                    delete args[i]['after'];
                }
                if (typeof args[i].then === "function" || typeof args[i].then === "string") {
                    control.then = args[i].then;
                    delete args[i]['then'];
                }
                if ((typeof args[i].async !== 'undefined') && (args[i].async === 'false' || typeof args[i].async === false)) {
                    async = false;
                }
                for (var p in args[i]) {
                    control.param[p] = args[i][p];
                }
            }
        }
        if (typeof control.event_name !== 'string' || control.event_name === null || control.event_name.length <= 0) {
            g4j.alert("g4jCall said: No event speicified");
            return;
        }
        if (typeof control.input_name !== 'string' || control.input_name === null || control.input_name.length <= 0) {
            g4j.alert("g4jCall said: No input speicified");
            return;
        }
        if (typeof control.action_name !== 'string' || control.action_name === null || control.action_name.length <= 0) {
            control.action_name = g4jUrlAction();
            // 只对URL这么处理！！！！
            if (!control.action_name.endsWith(".jspx")) {
                var iPos = control.action_name.lastIndexOf(".");
                if (iPos >= 0) {
                    control.action_name = control.action_name.substring(0, iPos) + ".jspx";
                } else {
                    control.action_name += ".jspx";
                }
                //alert(control.action_name);
            }
        }
        control.event_name = g4jCapUpper(control.event_name);
        try {
            var contentType = "application/x-www-form-urlencoded";
            var processData = true;
            var args = getActionInputs(evt);//g4jCall
            if (args.g4j_hasfile) {
                if (typeof FormData === 'undefined') {
                    g4j.alert("ERROR: 如果你采用IE，请采用IE10以上的版本，否则不支持通过ajax上传文件，如果采用其它浏览器，请升级到最新版本的浏览器。\nERROR: Please upgrade your browser to latest version. (e.g. IE 10.0 or above is required)");
                    return;
                }
                var formData = new FormData($(control.input_obj.form)[0]);
                formData.append("g4j_location", encodeURI(location.href));
                formData.append("g4j_control", encodeURI(control.input_name));
                if (typeof control.input_alias === 'string' && control.input_alias.length > 0) {
                    formData.append("g4j_alias", encodeURI(control.input_alias));
                }
                formData.append("g4j_event", encodeURI(control.event_name));
                formData.append("g4j_event_param", encodeURI(JSON.stringify(control.param)));
                formData.append("g4j_modulespecified", control.modulespecified);
                for (var p in args) {
                    if (p.endsWith("[path]")) {
                        formData.append(p, encodeURI(args[p]));
                    }
                }
                args = formData;
                processData = false; //这个重要
                contentType = false; //这个重要
            } else {
                jsonSet(args, "g4j_location", encodeURI(location.href));
                jsonSet(args, "g4j_control", encodeURI(control.input_name));
                if (typeof control.input_alias === 'string' && control.input_alias.length > 0) {
                    jsonSet(args, "g4j_alias", encodeURI(control.input_alias));
                }
                jsonSet(args, "g4j_event", encodeURI(control.event_name));
                jsonSet(args, "g4j_event_param", encodeURI(JSON.stringify(control.param)));
                jsonSet(args, "g4j_modulespecified", control.modulespecified);
            }
            var arg = {
                arg1: arg1,
                arg2: arg2,
                arg3: arg3,
                input_obj: control.input_obj,
                event: evt,
                input: control.input_name, //important!!!
                param: control.param,
                jspx: control.action_name,
                before: control.before,
                after: control.after,
                then: control.then
            };
            var ret = _g4j_beforeCall(arg, control.action_name, args);
            if (typeof ret !== 'undefined' && ret !== null && ret === false) {
                return false;
            }
            var g4jResult = null;
            var request = $.ajax({
                url: control.action_name,
                data: args,
                type: "POST",
                timeout: 180000,
                dataType: 'json',
                async: true,
                cache: false,
                contentType: contentType,
                processData: processData,
                success: function (data) { // g4jCall
                    g4jResult = g4jTranslateJsonResult(data);
                    _g4j_afterCall(arg, g4jResult);
                    return;
                }, //end of success,
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    var url = control.action_name;
                    var errorMessage;
                    switch (XMLHttpRequest.readyState) {
                        case 0:
                            errorMessage = "查询结果超时，你不要重新发送。以免重发。请过段时间检查发送记录以确定成功或失败。";
                            break;
                        case 4:
                            errorMessage = "HTTP " + XMLHttpRequest.status + ": " + errorThrown + "\nURL:" + url + "\nPlease check your network status.";
                            break;
                        default:
                            errorMessage = "HTTP " + XMLHttpRequest.status + ": " + errorThrown + "(XMLHttpRequest.readyState=" + XMLHttpRequest.readyState + ")\nURL:" + url + "\nPlease check your network status.";
                    }
                    g4jResult = {errcode: '-1', errmsg: errorMessage};
                    _g4j_afterCall(arg, g4jResult);
                    return;
                }
            });
            return g4jResult;
            //$.getJSON(action, args, function(){});
        } catch (e) {
            g4j.alert(e);
        }
    }

    function go(evt, newpage) {
        try {
            if (_$_query_button === null) {
                return false;
            }
            if (_$_pagecount === null) {
                g4j.alert('_$_pagecount undefined!!!');
                return;
            }
            if (newpage < 1) {
                newpage = 1;
            }
            if (newpage > _$_pagecount) {
                newpage = _$_pagecount;
            }
            var form = _$_query_button.form;
            if (form === null) {
                g4j.alert("queryButton(name: " + _$_query_button.name + ") must in a form!");
                return;
            }
            if (form.page === null) {
                g4j.alert("the form named '" + form.name + "' must has a hidden input named page!");
                return;
            }
            form.page.value = newpage;
            _$_query_button.click();
            //return g4jCall(evt);
        } catch (e) {
            g4j.alert("go() failed:" + e);
        }
    }

    function g4j_find(id_or_name) {
        var id = id_or_name;
        var o = document.getElementById(id);
        if (o !== null) {
            return o;
        }
        var name = id_or_name;
        var e = document.getElementsByName(name);
        if (e !== null) {
            if (e.length !== 1) {
                g4j.alert("There is " + e.length + " HTMLElement with the same name - " + name);
                return null;
            }
            return e[0];
        }
    }

    function goFirst(evt) {
        go(evt, 1);
    }

    function goPrior(evt) {
        go(evt, _$_page - 1);
    }

    function goNext(evt) {
        go(evt, _$_page + 1);
    }

    function goLast(evt) {
        go(evt, _$_pagecount);
    }

    function show_loading() {
        try {
            $("#loading").css('display', 'block');
        } catch (e) {
            g4j.alert("showLoading() said:" + e + ", Please make sure you had added jquery.js to your page!");
        }
    }
    function hide_loading() {
        try {
            $("#loading").css('display', 'none');
        } catch (e) {
            g4j.alert("showLoading() said:" + e + ", Please make sure you had added jquery.js to your page!");
        }
    }

    function Map(inputName, eventName) {
// ISHANMAO.USERS.PROVINCE[0]
        var arr = document.getElementsByName(inputName);
        if (arr.length <= 0) {
            g4j.alert("g4j.js find : Map() failed. No INPUT or SELECT named with '" + inputName + "'.");
            return false;
        }
        for (var i = 0; i < arr.length; i++) {
            switch (eventName) {
                case 'Click':
                    arr[i].onclick = function () {
                        var input = window.event.srcElement;
                        //var event = g4jCapUpper(window.event.type);
                        g4jCall(input, eventName);
                    };
                    break;
                case 'Change':
                    arr[i].onchange = function () {
                        var input = window.event.srcElement;
                        //var event = g4jCapUpper(window.event.type);
                        g4jCall(input, eventName);
                    };
                    break;
            }
        }
    }

    function verifyInput(name, value, reg, nullmsg, mactherror) {
        if (value.length === 0) {
            g4j.alert(name + nullmsg);
            return false;
        }
        if (!value.match(reg)) {
            g4j.alert(name + mactherror);
            return false;
        }
        return true;
    }

// 下面只是一个测试样例
    function checkInputUsingVerify(form) {
        if (!verifyInput("手机号码", form.reg_mobile.value, /\d{11}/, "没有填写", "不合法")) {
            return false;
        }
        if (!verifyInput("校验码", form.reg_verifyInputcode.value, /\d{4}/, "没有填写", "不合法")) {
            return false;
        }
        if (!verifyInput("常用邮箱", form.reg_email.value, /[\d\w]+@[\d\w]+\.[\d\w]+/, "没有填写", "不合法")) {
            return false;
        }
        if (!verifyInput("姓名", form.reg_name.value, /.+/, "没有填写", "必须为汉字")) {
            return false;
        }
        if (!verifyInput("密码", form.reg_pass.value, /\d{4}/, "没有填写", "必须包含字母和数字")) {
            return false;
        }
        return true;
    }

    /*
     <c:set var="cashing_sp" value="CALL ?=sp_ism_cashing_audit(@id, @yesno, ?){ISHANMAO}" scope="session"/>
     g4jSQL({
     query: 'cashing_sp',
     param: { rec_id:rec_id, yesno:rec_yesno },
     before: function(action,param){
     statusDialog.showModal();
     },
     after: function(jsonResult){
     statusDialog.remove();
     g4j.debug(jsonResult));
     }
     });
     */
    function g4jSQLExample() {
        /*
         <c:set scope="session" var="cashing_sp" 
         value="CALL ?=sp_ism_cashing_audit(@name,@sex,@age,@birthday, ?){ISHANMAO}" />
         */
        var statusDialog = dialog({width: 640, height: 50, title: '操作提示', content: '提现操作中...请稍候'});
        g4jSQL({
            query: 'cashing_sp',
            param: {
                name: 'SOMEONE',
                sex: 'Male',
                age: '25',
                birthday: '1991-07-07',
                scope: 'inputs'
            },
            before: function (action, param) {
                statusDialog.showModal();
            },
            after: function (jsonResult) {
                statusDialog.remove();
                var errcode = jsonResult.errcode;
                if (typeof errcode == 'undefined') {
                    g4j.alert("返回数据无法识别。" + JSON.stringify(jsonResult));
                    return;
                }
                if (errcode != '0') {
                    g4j.alert((jsonResult.errmsg) ? jsonResult.errmsg : JSON.stringify(jsonResult));
                    return;
                }
                errcode = jsonResult.COL1;
                if (typeof errcode === 'undefined') {
                    g4j.alert("返回数据没有COL1:" + JSON.stringify(jsonResult));
                    return;
                }
                if (errcode != '0') {
                    g4j.alert((jsonResult.COL2) ? jsonResult.COL2 : JSON.stringify(jsonResult));
                    return;
                }
                g4j.alert(jsonResult.COL2);
                return;
            }
        });
    }

    function g4jSQL(arg) {
        if (typeof $ === "undefined") {
            // Please add jquery.js to your page
            g4j.alert("请刷新页面，或确保网络状态良好（NO JQUERY)\n当前动作 - g4jSQL(" + toString(arg) + ")");
            return;
        }
        //
        var query = arg.query;
        if (typeof query === "undefined" || query.length < 0) {
            g4j.alert("No 'query' in g4jSQL()'s arguments. it is the name of session var for detailed sp or sql. examplels:\n" + g4jSQLExample);
            return;
        }
        var args = arg.param;
        if (typeof args !== "object") {
            args = {};
        }
        var maybeevt = null;
        try {
            maybeevt = window.event||arguments.callee.caller.arguments[0];
        } catch(e){}
        var pageInputs = getActionInputs(maybeevt);//g4jSQL
        for (var p in pageInputs) {
            if (typeof args[p] === 'undefined') {
                args[p] = pageInputs[p];
            }
        }
        var action = query + ".sp.jspx";
        var ret = _g4j_beforeCall(arg, action, args);
        if (typeof ret !== 'undefined' && ret !== null && ret === false) {
            return false;
        }
        var g4jResult = null;
        $.ajax({
            url: action,
            data: args,
            type: "POST",
            timeout: 180000,
            dataType: 'json',
            async: arg.async || false,
            success: function (data) { // g4jSQL
                g4jResult = g4jTranslateJsonResult(data);
                _g4j_afterCall(arg, g4jResult);
                return;
            }, //end of success,
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                switch (XMLHttpRequest.readyState) {
                    case 0:
                        g4jResult = {errcode: -1, errmsg: "查询结果超时，你不要重新发送。以免重发。请过段时间检查发送记录以确定成功或失败。"};
                        _g4j_afterCall(arg, g4jResult);
                        break;
                    case 4:
                        g4jResult = {errcode: -1, errmsg: "调用" + action + "失败。HTTP返回了" + XMLHttpRequest.status + "。错误提示内容：" + errorThrown + "。"};
                        _g4j_afterCall(arg, g4jResult);
                        break;
                    default:
                        g4jResult = {errcode: -1, errmsg: "调用" + action + "后，XMLHttpRequest: readyState=" + XMLHttpRequest.readyState + "。status=" + XMLHttpRequest.status + " errorThrown:" + errorThrown + "."};
                        _g4j_afterCall(arg, g4jResult);
                }
                return;
            },
            complete: function (XMLHttpRequest, status) { //请求完成后最终执行参数
                switch (status) {
                    case "timeout":
                        // 有专门的错误处理
                        break;
                    case "success":
                        // 有专门的错误处理
                        break;
                    case "error":
                        // 有专门的错误处理
                        break;
                    default:
                        g4jResult = {errcode: -1, errmsg: "completed, but status is '" + status + "'."};
                        _g4j_afterCall(arg, g4jResult);
                }
            }
        });
        return g4jResult;
    }

    function g4jExportExample() {
// 记得设置session变量： <c:set scope="session" var="excel_sql" value="select * from a{ISHANMAO}"/>
        g4jExport({
            query: 'excel_sql',
            param: {
                name: '清单',
                type: 'xls'
            },
            before: function (action, param) {
                // add your code here 
                return true;
            },
            after: function (jsonResult) {
                g4j.debug(jsonResult);
            }
        });
    }

    function g4jExport(arg) {
        if (typeof $ === "undefined") {
            // Please add jquery.js to your page
            g4j.alert("请刷新页面，或确保网络状态良好（NO JQUERY)\n当前动作 - g4jExport(" + toString(arg) + ")");
            return;
        }
        //
        var query = arg.query;
        if (typeof query === "undefined" || query.length < 0) {
            g4j.alert("No 'query' in g4jExport()'s arguments. it is the name of session var for detailed sp or sql. examplels:\n" + g4jExportExample.toString());
            return;
        }
        var args = arg.param;
        if (typeof args !== "object") {
            g4j.alert("No 'param' in g4jExport()'s arguments. it is a json object for sql's param. examplels:\n" + g4jExportExample.toString());
            return;
        }
        var maybeevt = null;
        try {
            maybeevt = window.event||arguments.callee.caller.arguments[0];
        } catch(e){}
        var pageParams = getActionInputs(maybeevt);//g4jExport
        extend(args, pageParams);
        var action = query + ".exp.jspx";
        var ret = _g4j_beforeCall(arg, action, args);
        if (typeof ret !== 'undefined' && ret !== null && ret === false) {
            return false;
        }
        $.ajax({
            url: action,
            data: args,
            type: "POST",
            timeout: 180000,
            dataType: 'json',
            success: function (data) { // g4jExport
                data = g4jTranslateJsonResult(data);
                _g4j_afterCall(arg, data);
                return;
            }, //end of success,
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                switch (XMLHttpRequest.readyState) {
                    case 0:
                        _g4j_afterCall(arg, {errcode: -1, errmsg: "查询结果超时，你不要重新发送。以免重发。请过段时间检查发送记录以确定成功或失败。"});
                        break;
                    case 4:
                        _g4j_afterCall(arg, {errcode: -1, errmsg: "调用" + action + "失败。HTTP返回了" + XMLHttpRequest.status + "。错误提示内容：" + errorThrown + "。"});
                        break;
                    default:
                        _g4j_afterCall(arg, {errcode: -1, errmsg: "调用" + action + "后，XMLHttpRequest: readyState=" + XMLHttpRequest.readyState + "。status=" + XMLHttpRequest.status + " errorThrown:" + errorThrown + "."});
                }
                return false;
            },
            complete: function (XMLHttpRequest, status) { //请求完成后最终执行参数
                switch (status) {
                    case "timeout":
                        // 有专门的错误处理
                        break;
                    case "success":
                        // 有专门的错误处理
                        break;
                    case "error":
                        // 有专门的错误处理
                        break;
                    default:
                        _g4j_afterCall(arg, {errcode: -1, errmsg: "completed, but status is '" + status + "'."});
                }
            }
        });
    }

    function g4jInvokeExample() {
        g4jInvoke({
            method: 'SomeJavaClass::someMethodName(arg-list)',
            param: {
                arg1: 'a',
                arg2: 124
            },
            before: function (action, param) {
                // add your code here for before invoking the java class's method
            },
            after: function (json) {
                // add your code here for after invoking the java class's method
            },
            then: function (json) {
                // add your code here for after invoking the java class's method
            }
        });
    }

    /*
     * g4jInvoke(args)
     * @params 
     *  args {type} json
     * @returns {undefined|Boolean}
     */
    function g4jInvoke(arg) {
        //
        var method = arg.method;
        if (typeof method === "undefined" || method === '') {
            g4j.alert("The element of method in the JSON of arg. \ne.g:\n" + g4jInvokeExample);
            return;
        }

        var event_param = arg.param;
        if (typeof event_param === 'undefined' || typeof event_param !== "object") {
            event_param = {};
        }
        var input_name = event_param.input || 'g4j';
        var event_name = 'invoke';
        if (typeof event_param.event === 'string') {
            event_name = event_param.event;
        } else if (typeof event_param.event !== "undefined") {
            var evt = event_param.event;
            if ((typeof evt.srcElement !== "undefined" || typeof evt.target !== "undefined") && (typeof evt.type !== "undefined")) {
                // evt 是 event
                input_name = (evt.srcElement || evt.target).name; //evt.srcElement(IE)/evt.target(Firefox)
                event_name = evt.type;
            }
        }
        var maybeevt = null;
        try {
            maybeevt = window.event||arguments.callee.caller.arguments[0];
        } catch(e){}
        var args = getActionInputs(maybeevt);//g4jInvoke
        jsonSet(args, "g4j_method", encodeURI(arg.method));
        jsonSet(args, "g4j_location", encodeURI(location.href));
        jsonSet(args, "g4j_control", encodeURI(input_name));
        jsonSet(args, "g4j_event", encodeURI(event_name));
        jsonSet(args, "g4j_event_param", encodeURI(JSON.stringify(event_param)));
        var action = "invoke.method.jspx";
        var ret = _g4j_beforeCall(arg, action, args);
        if (typeof ret !== 'undefined' && ret !== null && ret === false) {
            return false;
        }
        var g4jResult = null;
        $.ajax({
            url: action,
            data: args,
            type: "POST",
            timeout: 180000,
            dataType: 'json',
            async: arg.async || false,
            success: function (data) { // g4jInvoke
                g4jResult = g4jTranslateJsonResult(data);
                g4jResult['param'] = args;
                _g4j_afterCall(arg, g4jResult);
                return;
            }, //end of success,
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                switch (XMLHttpRequest.readyState) {
                    case 0:
                        g4jResult = {errcode: -1, errmsg: "查询结果超时，你不要重新发送。以免重发。请过段时间检查发送记录以确定成功或失败。"};
                        break;
                    case 4:
                        g4jResult = {errcode: -1, errmsg: "调用" + action + "失败。HTTP返回了" + XMLHttpRequest.status + "。错误提示内容：" + errorThrown + "。"};
                        break;
                    default:
                        g4jResult = {errcode: -1, errmsg: "调用" + action + "后，XMLHttpRequest: readyState=" + XMLHttpRequest.readyState + "。status=" + XMLHttpRequest.status + " errorThrown:" + errorThrown + "."};
                }
                _g4j_afterCall(arg, g4jResult);
                return false;
            },
            complete: function (XMLHttpRequest, status) { //请求完成后最终执行参数
                switch (status) {
                    case "timeout":
                        // 有专门的错误处理
                        break;
                    case "success":
                        // 有专门的错误处理
                        break;
                    case "error":
                        // 有专门的错误处理
                        break;
                    default:
                        g4jResult = {errcode: -1, errmsg: "completed, but status is '" + status + "'."};
                        _g4j_afterCall(arg, g4jResult);
                }
            }
        });
        return g4jResult;
    }

    function getScope(controllerName) {
        var appElement = document.querySelector('[ng-controller=' + controllerName + ']');
        var $scope = angular.element(appElement).scope();
        return $scope;
    }

    function scopeApply($scope) {
        $scope.$apply();
    }

    // 这个用来初始化所有g4j-form的表单
    function g4jForm(){
        // --- 旧方式，不支持动态生成的表单
        $(".g4j-form").each(function (e) {
            //$(".g4j-form").each(function (e) {
            //  action="formupdate.jspx" method="POST" enctype="multipart/form-data" target="hiddenFrame"
            var action = $(this).attr('action');
            if (isInvalidOrEmptyString(action) || action === 'g4j') {
                // 它没有指定的时候，才设置成formupdate.jspx
                action = "formupdate.jspx";
            } else {
                var iPos = action.indexOf(".jspx");
                if (iPos !== action.length - ".jspx".length && action.indexOf("?") <= 0) {
                    action += ".jspx";
                }
            }
            action += "?g4j-form=" + ($(this).attr("id") || 'ANONYMOUS_FORM');
            var databind = $(this).attr('data-update') || $(this).attr('data-bind');
            var g4j_onerror = $(this).attr("onerror");
            if (typeof g4j_onerror !== 'string' || g4j_onerror.length <= 0) {
                g4j_onerror = "";
            }
            var g4j_onended = $(this).attr("onended");
            if (typeof g4j_onended !== 'string' || g4j_onended.length <= 0) {
                g4j_onended = "";
            }
            if (!isInvalidOrEmptyString(databind)) {
                action += "&g4j-update=" + databind;
                ////
                var update_arr = databind.split(";");
                if (action.indexOf("formupdate.jspx") >= 0) {
                    var jsonBackup = {};
                    for (var i = 0; i < update_arr.length; i++) {
                        var update = update_arr[i];
                        // DSN_NAME.TABLE_NAME[n]
                        var iPos1 = update.indexOf("[");
                        var iPos2 = update.indexOf("]");
                        if (iPos1 < 0 || iPos2 <= iPos1) {
                            break;
                        }
                        var pkstring = update.substring(iPos1 + 1, iPos2).trim();
                        if (pkstring.length <= 0) {
                            continue;
                        }
                        var fieldprefix = update.substring(0, iPos1);
                        var pk_arr = pkstring.split(",");
                        var a = $(this).serializeArray();
                        $.each(a, function () {
                            //jsonSet(o, this.name, encodeURI(this.value), false);
                            var name = this.name;
                            var value = this.value;
                            var iPos1 = name.indexOf("[");
                            var iPos2 = name.indexOf("]");
                            if (iPos1 <= 0 || iPos2 <= iPos1) {
                                return;
                            }
                            var name_match = name.substring(0, iPos1) + name.substring(iPos2 + 1);
                            var index = parseInt(name.substring(iPos1 + 1, iPos2));
                            if (!(index >= 0 && index <= 65535)) {
                                return;
                            }
                            for (var pk_i = 0; pk_i < pk_arr.length; pk_i++) {
                                var pk = pk_arr[pk_i];
                                if (name_match === fieldprefix + "." + pk) {
                                    jsonBackup[name_match + "[" + index + "]"] = value;
                                    continue;
                                }
                                if (name_match === pk) {
                                    jsonBackup[fieldprefix + "." + name_match + "[" + index + "]"] = value;
                                    continue;
                                }
                            }
                        });
                        $("[name^='" + fieldprefix + "']").each(function (e) {
                            var name = $(this).attr('name');
                            var iPos1 = name.indexOf("[");
                            var iPos2 = name.indexOf("]");
                            var name_match = name;
                            if (iPos1 <= 0 || iPos2 <= iPos1) {
                                return;
                            }
                            name_match = name.substring(0, iPos1) + name.substring(iPos2 + 1);
                            var index = parseInt(name.substring(iPos1 + 1, iPos2));
                            if (!(index >= 0 && index <= 65535)) {
                                return;
                            }
                            for (var pk_i = 0; pk_i < pk_arr.length; pk_i++) {
                                var pk = pk_arr[pk_i];
                                if (name_match === fieldprefix + "." + pk) {
                                    jsonBackup[name_match + "[" + index + "]"] = $(this).val();
                                }
                            }
                        });
                    }
                    // {"'ISHANMAO.DEMO.ID'[10]":"15","'ISHANMAO.DEMO.ID'[11]":"16","'ISHANMAO.DEMO.ID'[12]":"17","'ISHANMAO.DEMO.ID'[13]":"18","'ISHANMAO.DEMO.ID'[14]":"19","'ISHANMAO.DEMO.ID'[15]":"20","'ISHANMAO.DEMO.ID'[1]":"1","'ISHANMAO.DEMO.ID'[2]":"2","'ISHANMAO.DEMO.ID'[3]":"6","'ISHANMAO.DEMO.ID'[4]":"7","'ISHANMAO.DEMO.ID'[5]":"9","'ISHANMAO.DEMO.ID'[6]":"11","'ISHANMAO.DEMO.ID'[7]":"12","'ISHANMAO.DEMO.ID'[8]":"13","'ISHANMAO.DEMO.ID'[9]":"14"}
                    $("<textarea name=\"g4j-primarykeys\" style=\"display:none\">" + JSON.stringify(jsonBackup) + "</textarea>").insertAfter($(this).find("INPUT:last"));
                }
                ////
            }
            var submits = "";
            $(this).find("INPUT[type='submit']").each(function (e) {
                submits += $(this).attr("name") + "/";
            });
            action += "&g4j_controls=" + submits;
            action += "&g4j_onended=" + g4j_onended;
            $(this).attr('action', action);
            $(this).attr('method', "POST");
            $(this).attr('enctype', "multipart/form-data");
            $(this).attr('target', "g4j_hidden_frame");
            if ($('#g4j_hidden_frame').size() <= 0) {
                $("<iframe name='g4j_hidden_frame' id='g4j_hidden_frame' onload='g4j_on_hidden_frame()' src='about:blank' style='display:none;width:1px;height:1px;'></iframe>").insertAfter(this);
            }
            $(this).find("INPUT").each(function (e) {
                if (typeof $(this).attr('data-type') === 'string' && $(this).attr('data-type').toLowerCase() === 'autosave' || $(this).hasClass("g4j-autosave")) {
                    $(this).change(function (event) {
                        var form = this.form;
                        if (form === null) {
                            g4j.alert("No form for this INPUT or SELECT or TEXTAREA (a valid auto-save input must be in a form");
                            return;
                        }
                        var name = this.name;
                        var iPos = name.indexOf("[");
                        var iEndPos = name.indexOf("]");
                        if (iPos < 0 || iEndPos <= iPos) {
                            g4j.alert("Invalid name for this INPUT or SELECT or TEXTAREA (a valid name is like DSN.TNAME.NAME[n] or DSN.TNAME[n].NAME)");
                            return;
                        }
                        var prefix = name.substring(iPos, iEndPos + 1);
                        $(form).submit();
                    });
                }
            });
            $(this).removeClass("g4j-form");
            $(this).addClass("g4j-formed");
        });
    }

    g4j = {
        app: null,
        scope: null,
        location: null,
        window: null,
        http: null,
        onEvent: function (tagName, label, eventName, worker) {
            tagName = tagName.toUpperCase();
            var inputs = document.getElementsByTagName(tagName);
            if (inputs === null || inputs.length <= 0) {
                return 0;
            }
            var count = 0;
            for (var i = 0; i < inputs.length; i++) {
                var input = inputs[i];
                if (equalWithNoSpace(input.value, label) || equalWithNoSpace(input.name, label) || equalWithNoSpace(input.id, label)) {
                    var f = function () {
                        if (typeof worker === 'string') {
                            if (worker.match(/(^\w+::)/g)) {
                                g4jInvoke({method: worker});
                            } else {
                                g4jSQL({query: worker});
                            }
                        } else if (typeof worker === 'function') {
                            worker();
                        } else {
                            g4j.alert("onEvent said: typeof worker: " + (typeof worker));
                        }
                    };
                    if (eventName.toLowerCase() === 'click') {
                        $(input).click(f);
                    } else if (eventName.toLowerCase() === 'change') {
                        $(input).change(f);
                    }
                    count++;
                }
            }
            return count;
        },
        click: function (label, worker) {
            var count = 0;
            count += g4j.onEvent("BUTTON", label, "click", worker);
            count += g4j.onEvent("INPUT", label, "click", worker);
            count += g4j.onEvent("SELECT", label, "click", worker);
            if (count <= 0) {
                g4j.alert("Cannot find a input named '" + label + "' or has the ID of '" + label + "'  or the value of '" + label + "' ");
                return false;
            }
            return true;
        },
        change: function (label, worker) {
            var count = 0;
            //count += g4j.onEvent("BUTTON", label, "change", worker);
            count += g4j.onEvent("INPUT", label, "change", worker);
            count += g4j.onEvent("SELECT", label, "change", worker);
            if (count <= 0) {
                g4j.alert("Cannot find a input named '" + label + "' or has the ID of '" + label + "'  or the value of '" + label + "' ");
                return false;
            }
            return true;
        },
        enumInputs: function (label, func) {
            var inputs = document.getElementsByTagName("INPUT");
            if (inputs === null || inputs.length <= 0) {
                return false;
            }
            var count = 0;
            for (var i = 0; i < inputs.length; i++) {
                var input = inputs[i];
                if (equalWithNoSpace(input.value, label) || equalWithNoSpace(input.name, label) || equalWithNoSpace(input.id, label)) {
                    func(input);
                }
            }
        },
        getInput: function (tagName, label) {
            tagName = tagName.toUpperCase();
            var returnValue = null;
            var inputs = document.getElementsByTagName(tagName);
            if (inputs === null || inputs.length <= 0) {
                return false;
            }
            var count = 0;
            label = label.toLowerCase();
            for (var i = 0; i < inputs.length; i++) {
                var input = inputs[i];
                if (input.name.toLowerCase() === label || input.id.toLowerCase() === label) {
                    returnValue = input.value;
                    count++;
                }
            }
            if (count <= 0) {
                return null;
            }
            if (count > 1) {
                g4j.alert("More than one inputs has the name or ID of '" + label + "'.");
                return returnValue;
            }
            return returnValue;
        },
        formInput: function (label) {
            var returnValue = getInput('INPUT', label);
            if (returnValue === null) {
                returnValue = getInput('SELECT', label);
                if (returnValue === null) {
                    g4j.alert("Cannot find a input named '" + label + "' or has the ID of '" + label + "' ");
                    return returnValue;
                }
            }
            return returnValue;
        },
        version: function () {
            return ver;
        },
        form: g4jForm,
        call: g4jCall,
        sql: g4jSQL,
        sp: g4jSQL,
        del: g4jDEL,
        invoke: g4jInvoke,
        navigate: g4jNavigate,
        exp: g4jExport, /*不能用export，会引起IE8以前的版本报错，因为export是保留字*/
        lasterror: "",
        debug: function (s) {
            if (typeof s === 'object') {
                alert(JSON.stringify(s));
            } else {
                alert(s);
            }
        },
        alert: function (msg) {
            if (typeof msg === 'undefined' || msg === null) {
                return;
            }
            if (typeof msg === 'object') {
                var e = msg;
                if (typeof msg.message !== 'undefined' && typeof msg.stack !== 'undefined') {
                    console.log("ERROR:" + e.message + "\nSTACK:" + e.stack);
                    msg = "Javascript Exception: " + e.message + ", please refer to the navigator's console log.";
                } else {
                    msg = (new String(e)).toString();
                }
            }
            if (typeof msg !== 'string') {
                msg = (new String(e)).toString();
            }
            if (typeof msg !== 'string') {
                alert("g4j.js 报告：奇怪的转换(1957).");
            }
            if (msg === '') {
                return;
            }
            // 为了兼容
            if (typeof _$_messageBox === 'function') {
                _$_messageBox(msg);
            } else {
                // 如果当前窗口有 messageBox
                if (typeof messageBox === 'function') {
                    messageBox(msg);
                } else {
                    // 如果上一级窗口有 messageBox
                    if (typeof parent.messageBox === 'function') {
                        parent.messageBox(msg);
                    } else {
                        alert(msg);
                    }
                }
            }
            if (msg.indexOf('需要重新登录才能继续操作') >= 0) {
                top.location.href = ".jspx?sessionId=" + new Date();
            }
        },
        ver: "2.0.2017.03.31.14.00.00"
    };

//g4jDEL(1);
//g4jDEL("2");
//g4jDEL("[2,3,4,5]");
//g4jDEL("abc");
//g4jDEL(null);
//g4jDEL([2,3,4,5]);
    function g4jDEL(clcko, arg, before, after) {
        if (typeof arg === 'undefined' || arg === null) {
            g4j.alert("Arguemnt not found for g4jDEL(arg)");
            return;
        }
        var arr = [];
        if (typeof arg === 'number') {
            arr[arr.length] = arg;
        } else
        if (typeof arg === 'string') {
            if (parseInt(arg) >= 0 && parseInt(arg) <= 65535) {
                arr[arr.length] = parseInt(arg);
            } else {
                try {
                    var obj = JSON.parse(arg);
                } catch (e) {
                    g4j.alert("Cannot parse json - " + arg);
                    return;
                }
                if (typeof obj === 'object' && typeof obj.length !== 'undefined') {
                    arr = obj;
                }
            }
        } else
        if (typeof arg === 'object' && typeof arg.length !== 'undefined') {
            arr = arg;
        }
        if (arr.length <= 0) {
            g4j.alert("Arguemnt not found for g4jDEL(arg), now arg: " + (arg === null) ? '(null)' : arg);
            return;
        }
        var form = null;
        var parent = $(clcko).parent();
        for (var i = 0; parent !== null && parent.length > 0; i++) {
            if (parent.hasClass('g4j-form')) {
                form = parent;
                break;
            }
            parent = parent.parent();
        }
        if (form === null) {
            g4j.alert("No element with the class named 'g4j-form' in current page or it is too deep (more than 10 parent)!");
            return;
        }
        var callparam = {
            method: 'DefaultJspPage::deleteDBHelper((String)dbi,(String)rows)',
            param: {
                dbi: $(form).children("[name='g4j-update']").val(),
                rows: JSON.stringify(arr)
            }
        };
        if (typeof before === 'function') {
            callparam.before = before;
        }
        if (typeof after === 'function') {
            callparam.after = after;
        }
        g4jInvoke(callparam);
        //form.action = 'form-update.jspx?DEL_ID_SET=' + encodeURI(JSON.stringify(arr))
    }


    function g4jNavigate(jsonArguments) {
        if (jsonArguments === null) {
            g4j.alert("g4jNavigate() said: jsonArguments must NOT be null!!!!");
            return;
        }
        if (typeof jsonArguments.jsp === 'undefined') {
            g4j.alert("g4jNavigate() said: jsonArguments must has the member variable named 'jsp'!!!!");
            return;
        }
        // 兼容旧的代码，旧的代码中，在jsonArguments中没有id，只有jsp变量
        var divId = jsonArguments.id || jsonArguments.jsp;
        var jspName = jsonArguments.jsp;
        if (typeof $ === 'undefined') {
            g4j.alert("No JQUERY plugin included in this page!!!!");
            return;
        }
        if (typeof $.ajax === 'undefined') {
            g4j.alert("No valid JQUERY plugin included in this page befause $.ajax is undefined !!!!");
            return;
        }
        if ($('#' + divId).length <= 0) {
            g4j.alert("No element with the id of '" + divId + "' in this page which g4jNavigate() required!");
            return;
        }
        var maybeevt = null;
        try {
            maybeevt = window.event||arguments.callee.caller.arguments[0];
        } catch(e){}
        var param = getActionInputs(maybeevt);
        for (var p in jsonArguments) {
            param[p] = jsonArguments[p];
        }
        //g4j.debug(param);
        if (jspName === divId) {
            jspName += ".jsp";
        }
        var url = jspName; // + location.search; 
        var request = $.ajax({
            url: url,
            data: param,
            type: "POST",
            timeout: 180000,
            dataType: 'html',
            success: function (data) { // g4jNavigate
                // 不用它, 因为是html --- data['param'] = jsonArguments;
                var iPos = data.indexOf(">");
                if (iPos > 0) {
                    iPos++;
                    var iEndPos = data.lastIndexOf("<");
                    if (iEndPos > iPos) {
                        data = data.substring(iPos, iEndPos);
                    }
                }
                $('#' + divId).html(data);
                initAllElementsActionScript();
                if (typeof jsonArguments.then === 'function') {
                    jsonArguments.then();
                }
                return;
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                switch (XMLHttpRequest.readyState) {
                    case 0:
                        g4j.alert("查询结果超时，请重试。");
                        break;
                    case 4:
                        g4j.alert("HTTP " + XMLHttpRequest.status + ": " + errorThrown + "\nURL:" + url + "\nPlease check your network status.");
                        break;
                    default:
                        g4j.alert("HTTP " + XMLHttpRequest.status + ": " + errorThrown + "(XMLHttpRequest.readyState=" + XMLHttpRequest.readyState + ")\nURL:" + url + "\nPlease check your network status.");
                }
                return false;
            }
        });
    }

    function goPage(jspName, page) {
        var param = {};
        param["jsp"] = jspName;
        param["id"] = jspName;
        param[param["id"] + "_page"] = page;
        g4jNavigate(param);
    }
    /*
     * 新的翻页函数
     * @param {type} page
     * @returns {undefined}
     */
    function pageTo(theClicked, page) {
        var pageToppestElement = null;
        var parent = $(theClicked).parent();
        for (var i = 0; parent !== null && parent.length > 0; i++) {
            if (parent.hasClass('g4j-page')) {
                pageToppestElement = parent;
                break;
            }
            parent = parent.parent();
        }
        if (pageToppestElement === null) {
            g4j.alert("No element with the class named 'g4j-page' in current page or it is too deep (more than 10 parent)!");
            return;
        }
        var divId = pageToppestElement.attr('id');
        if (typeof divId === 'undefined' || divId === null) {
            g4j.alert("The element with the class named 'g4j-page' has no ID!");
            return;
        }
        var pathName = pageToppestElement.attr('data-path');
        if (typeof pathName === 'undefined' || pathName === null) {
            pathName = divId + ".jsp";
        }
        var param = {};
        param["jsp"] = pathName;
        param["id"] = divId;
        param[param["id"] + "_page"] = page;
        param["then"] = function () {
            pageToppestElement.css("display", "block");
        };
        g4jNavigate(param, pageToppestElement);
    }

    function toolGetModuleNameFromPathName(pathname) {
        var moduleName = pathname;
        if (moduleName.indexOf("/") === 0) {
            moduleName = moduleName.substring(1);
            ;
        }
        if (moduleName.indexOf("/") > 0) {
            moduleName = moduleName.substring(moduleName.indexOf("/") + 1);
        }
        if (moduleName === "") {
            moduleName = "index.jsp";
        }
        if (moduleName.toLowerCase().lastIndexOf(".jsp") === moduleName.length - ".jsp".length || moduleName.toLowerCase().lastIndexOf(".jspx") === moduleName.length - ".jspx".length) {
            moduleName = moduleName.substring(0, moduleName.lastIndexOf(".jsp"));
        }
        moduleName = moduleName.replace(/\//g, ".");
        return moduleName;
    }

    function initAllElementsActionScript() {
        // onclick="method:MobilePages::test(a,b,c)|g4j.debug(e)"
        // onclick="query:SP_ISM_WALLET(a,b,c)|g4j.debug(e)"
        // 用$(document).on,不要用这个,因为下面这个可以对动态生成的html也管用 
        // $(".g4j-button").each(function (e) {
        // g4j-button(onclick) g4j-input(onchange) g4j-document
        if ($(document.body).hasClass("g4j-document") || $(document.body).hasClass("g4j")) {
            var jsonParam = {
                input: 'Page',
                event: 'Init',
                jspx: $(document.body).attr('data-module') || $(document.body).attr('data-bind')
            };
            //g4j.debug(jsonParam);
            g4jCall(jsonParam);
        }
        if (typeof $(document).on === 'undefined') {
            g4j.alert("你需要升级你的jquery到2.0.0以上。");
            return;
        }
        $(document).on("change", ".g4j-input", function (e) {
            return g4jCall(e);
        });
        $(document).on("click", ".g4j-button", function (e) {
            var type = $(this).attr('type');
            if (type === 'submit' || type === 'SUBMIT') {
                g4j.alert("There is some g4j-button has the INPUT-type of 'submit'! its ID is " + $(this).attr('id') + " its NAME is " + $(this).attr('name'));
                return;
            }
            var info = g4jReadFromEvent(e);
            if (isInvalid(info.data_method)) {
                return g4jCall(e);//g4jCall能自动读取其它属性等等信息
            }
            if (isInvalid(info.data_module)) {
                info.data_module = toolGetModuleNameFromPathName(location.pathname);
            }
            var param = info.param;
            var before = info.before;
            var after = info.after;
            var action_info = null;
            if (info.data_module === 'query') {
                action_info = 'query:' + info.data_method.trim();
                var key = 'query:';
                action_info = action_info.substring(key.length);
                var query = info.data_method.trim();
                var iStartPos = query.indexOf("(");
                var iEndPos = query.indexOf(")");
                if (iStartPos >= 0 && iEndPos > iStartPos) {
                    // 表示这个串中有定义参数
                }
                var iEndOfSign = query.indexOf(';');
                if (iEndOfSign >= 0) {
                    query = query.substring(0, iEndOfSign);
                }
                if (query.length === 0) {
                    g4j.alert("There is some g4j-button has invalid attribute of onclick! its ID is " + $(this).attr('id') + " its NAME is " + $(this).attr('name'));
                    return;
                }
                param['g4j_query'] = encodeURIComponent(query);
                g4jSQL({
                    query: "do.sp.jspx",
                    param: param,
                    before: before,
                    after: after
                }); // end of g4jSQL
                return;
            } else {
                action_info = 'method:' + info.data_module.trim() + '::' + info.data_method.trim();
                var key = 'method:';
                action_info = action_info.substring(key.length);
                var method = info.data_module.trim() + '::' + info.data_method.trim();
                var iEndOfSign = method.indexOf(';');
                if (iEndOfSign >= 0) {
                    method = method.substring(0, iEndOfSign);
                }
                if (method.length === 0) {
                    g4j.alert("There is some g4j-button has invalid attribute of onclick! its ID is " + $(this).attr('id') + " its NAME is " + $(this).attr('name'));
                    return;
                }
                g4jInvoke({
                    method: method,
                    param: param,
                    before: before,
                    after: after
                }); // end of g4jInvoke
                return;
            }
            g4j.alert("There is some g4j-button has valid attribute of onclick! its ID is " + $(this).attr('id') + " its NAME is " + $(this).attr('name') + "\n"
                    + "Example:\n"
                    + "onclick=\"method:MobilePages::test(a,b,c)|g4j.debug(e)\"\n"
                    + "or:\n"
                    + "onclick=\"query:SP_ISM_WALLET(a,b,c)|g4j.debug(e)\"\n");
            return;
        });
        $(document).on("click", ".g4j-delete", function () {
            var button_name = $(this).attr('name');
            var form_updates = $(this).attr('data-update') || $(this).attr('data-bind');
            var arg = $(this).attr('data-rows');
            var before = $(this).attr('data-before') || $(this).attr('before');
            var success = $(this).attr('data-success') || $(this).attr('success');
            var error = $(this).attr('data-error') || $(this).attr('error');
            if (typeof form_updates === 'undefined' || form_updates === null) {
                g4j.alert("A g4j-delete HTMLElement must has data-bind attribute.");
                return;
            }
            if (typeof arg === 'undefined' || arg === null) {
                g4j.alert("A g4j-delete HTMLElement must has data-rows attribute.");
                return;
            }
            var reg = /\d+[\,\d*]*|/g;
            if (!arg.match(reg)) {
                g4j.alert("A g4j-delete HTMLElement must has data-bind attribute. data-bind must be one or more numbers splited by colon(e.g. 1, or 1,2,3 or 1,2,)");
                return;
            }
            var arr = [];
            if (arg.indexOf(",") > 0) {
                try {
                    var obj = JSON.parse('[' + arg + ']');
                    if (typeof obj === 'object' && typeof obj.length !== 'undefined') {
                        arr = obj;
                    }
                } catch (e) {
                    g4j.alert("Cannot parse json - " + arg);
                    return;
                }
            } else {
                arr[arr.length] = parseInt(arg);
            }
            if (arr.length <= 0) {
                g4j.alert("Row-indexes not found for delete, A g4j-delete HTMLElement must has data-bind attribute. data-bind must be one or more numbers splited by colon(e.g. 1, or 1,2,3 or 1,2,)");
                return;
            }
            var delparam = {
                button_name: button_name,
                dbi: form_updates,
                rows: JSON.stringify(arr)
            };
            var callparam = {
                method: 'DefaultJspPage::deleteDBHelper((String)dbi,(String)rows)',
                param: delparam,
                before: function (action, param) {
                    if (isInvalid(before)) {
                        return true;
                    }
                    var ret = true;
                    try {
                        if (typeof before === 'function') {
                            ret = before(delparam);
                            if (ret !== true && ret !== false) {
                                g4j.alert("The attribute of 'data-before' or 'before' specified a function which does NOT return boolean!");
                                ret = false;
                            }
                        } else {
                            if (typeof before === 'string') {
                                var js = before;
                                if (js.indexOf('(') <= 0 && js.indexOf(')') <= 0 && js.indexOf(';') <= 0 && js.indexOf('\'') <= 0 && js.indexOf('\"') <= 0 && js.indexOf('{') <= 0 && js.indexOf('}') <= 0) {
                                    js = js + "(delparam)";
                                } else {
                                    if (js.trim().startsWith("return ") || js.trim().startsWith("return\t") || js.trim().startsWith("return\t") || js.trim().startsWith("return\n")) {
                                        js = js.trim().substring("return\t".length);
                                    }
                                }
                                ret = eval(js);
                            }
                        }
                    } catch (e) {
                        g4j.alert(e);
                        ret = false;
                    }
                    return ret;
                },
                after: function (res) {
                    var js = null;
                    delparam.errcode = res.errcode;
                    delparam.errmsg = res.errmsg;
                    if (parseInt(res.errcode) === 0) {
                        if (isInvalid(success)) {
                            g4j.alert("删除成功(Record(s) has been deleted OKay)");
                            return true;
                        }
                        js = success;
                    } else {
                        if (isInvalid(error)) {
                            g4j.alert(res.errmsg);
                            return true;
                        }
                        js = error;
                    }
                    if (js.indexOf('(') <= 0 && js.indexOf(')') <= 0 && js.indexOf(';') <= 0 && js.indexOf('\'') <= 0 && js.indexOf('\"') <= 0 && js.indexOf('{') <= 0 && js.indexOf('}') <= 0) {
                        js = js + "(delparam)";
                    } else {
                        if (js.trim().startsWith("return ") || js.trim().startsWith("return\t") || js.trim().startsWith("return\t") || js.trim().startsWith("return\n")) {
                            js = js.trim().substring("return\t".length);
                        }
                    }
                    try {
                        return eval(js);
                    } catch (e) {
                        g4j.alert(e);
                        g4j.alert("最后的操作结果是：" + res.errmsg);
                        return false;
                    }
                }
            };
            g4jInvoke(callparam);
        });
        if (typeof g4j.form !== 'function'){
            console.log("WARNING: g4j.form is not a function ,therefore g4j-form may not processed correctly!");
        } else {
            g4j.form();
        }
    }

    if (typeof $ === "undefined") {
        // Please add jquery.js to your page
        alert("请刷新页面，或确保网络状态良好（NO JQUERY)");
    }

    var init_hidden_frame = false;

    function g4j_on_hidden_frame() {
        if (!init_hidden_frame) {
            // 首次装载不用管它
            init_hidden_frame = true;
            return;
        }
        if (typeof g4j_hidden_frame.getResponseJSON === 'undefined') {
            g4j.alert('无法访问网络,请检查当前网络连接情况.');
            return;
        }
        var res = g4j_hidden_frame.getResponseJSON();
        if (!$.isPlainObject(res)) {
            g4j.alert('The function of getResponseJSON() in iframe do NOT return valid JSON object.\nURL:' + urlstring);
            return;
        }
        if (typeof res.onended === 'undefined') {
            g4j.alert('The JSON returned by getResponseJSON() in iframe has no the property of \"onended\".\nURL:' + urlstring);
            return;
        }
        var g4j_onended = res.onended;
        if (g4j_onended === null) {
            g4j_onended = "";
        } else {
            if (typeof g4j_onended === 'function') {
                g4j_onended(res);
                return;
            }
            g4j_onended = g4j_onended.trim();
        }
        if (g4j_onended === '') {
            var arg = {
                input: res.input,
                after: res.onended,
                form: res.form,
                query: res.query
            };
            var data = g4jTranslateJsonResult(res);
            _g4j_afterCall(arg, data); // g4j-form
        } else {
            try {
                if (g4j_onended.indexOf("(") >= 0) {
                    eval(g4j_onended);
                } else {
                    eval(g4j_onended + "(res)");
                }
            } catch (e) {
                g4j.alert(e);
            }
        }
    }

    $(function () {
        initCheck();
    });

    var initialized = false;

    function initCheck() {
        if (initialized) {
            return;
        }
        if (typeof $ === "undefined") {
            // Please add jquery.js to your page
            g4j.alert("请刷新页面，或确保网络状态良好（NO JQUERY)");
            return;
        }
        if (typeof JSON === "undefined") {
            g4j.alert("当前的浏览器不支持 JSON ,请关闭兼容模式，或引入json2.js。");
            return;
        }
        if (JSON.stringify === null || typeof JSON.stringify === 'undefined') {
            g4j.alert("当前的浏览器不支持 JSON.stringify ,请升级或更换浏览器。");
            return;
        }
        if (typeof $.ajaxSetup === 'function') {
            $.ajaxSetup({
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    if (XMLHttpRequest.readyState === 4) {
                        console.log("ajax get/post failed(XMLHttpRequest.readyState:" + XMLHttpRequest.readyState + "), detail: http status:" + XMLHttpRequest.status + ", textStatus:" + textStatus + ", errorThrown:" + errorThrown + ".");
                    }
                    return false;
                }
            });
        }
        if (typeof onPageInit === 'undefined') {
            onPageInit = function () {};
        }
        if (typeof $(document.body).attr('onload') === 'undefined') {
            g4j.lasterror += "WARNING: onPageInit() should not be call in rear end!\n";
        }
        initAllElementsActionScript();
        onPageInit();
        initialized = true;
    }

    if (typeof angular === 'object') {
        g4j.app = angular.module("g4jApp", []);
        g4j.app.controller("g4jController", function ($scope, $location, $window, $http) {
            g4j.scope = $scope;
            g4j.location = $location;
            g4j.window = $window;
            g4j.http = $http;
        });
    }
}

